package cn.kgc.thread.demo3;

import java.util.concurrent.*;

/**
 * <p>异步编排任务</p>
 *
 * @author 李孟鸠
 * @Date: 2022年12月14日9:22
 */
public class Demo1 {
    private static ThreadPoolExecutor  executor=new ThreadPoolExecutor(
            10,
            10,
            1, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.DiscardPolicy());


    //异步编排任务
    //supplyAsync  有返回值
    //runAsync  无返回值

    //whenCompleteAsync 不需要返回值
    //exceptionally  需要返回值 异常处理
    //handleAsync  入参传入的是任务1的返回值与exception信息

    //thenApplyAsync    //入参只能传入任务1的返回值  获得参数 不能录入异常
    //thenAcceptAsync  //有参数没有返回值  不能录入异常
    //thenRunAsync   //无参数无返回值  不能录入异常

    //thenCombineAsync   //组合任务1和任务2的结果  获得入参  有返回值
    //thenAcceptBothAsync  //组合任务1和任务2的结果，有参数没有返回值
    //runAfterBothAsync   //组合任务1和任务2的结果，无参数无返回值


    //applyToEitherAsync  //任务1和任务2任意一个完成，获得入参，有返回值
    //acceptEitherAsync //任务1和任务2任意一个完成，有参数没有返回值
    //runAfterEitherAsync  //任务1和任务2任意一个完成，无参数无返回值
    public static void main(String[] args) throws Exception {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {

            System.out.println("开始执行任务");
            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(15000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("开始执行任务2中的内容");
            try {
                Thread.sleep(11000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务2执行完毕");
            return "任务2的返回值";
        }, executor);

//         CompletableFuture.allOf(future1, future2).join();
//        System.out.println("所有任务执行完毕，就执行");
         CompletableFuture.anyOf(future1, future2).join();
        System.out.println("只要有一个任务执行完毕，就执行");


    }

    private static void method9() throws InterruptedException, ExecutionException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {

            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        }, executor);

        CompletableFuture<String> future3 = future1.applyToEitherAsync(future2, (result1) -> {
            System.out.println("执行任务3中的内容");
            System.out.println("任务3中获得前2个任务的结果" + result1);
            return "任务3的返回值";
        }, executor);

        System.out.println("任务3的返回值" + future3.get());

 //acceptEither
        CompletableFuture<Void> future4 = future1.acceptEitherAsync(future2, result -> {
            System.out.println("执行任务4中的内容");
            System.out.println("任务4中获得前2个任务的结果" + result);
        }, executor);

        System.out.println("任务4的返回值" + future4.get());

        CompletableFuture<Void> future5 = future1.runAfterEitherAsync(future2, () -> {
            System.out.println("执行任务5中的内容");
        }, executor);
        System.out.println("任务5的返回值" + future5.get());
    }

    private static void method8() throws InterruptedException, ExecutionException {
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {

            System.out.println("执行任务1中的内容");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务1的返回值";
        }, executor);

        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务2中的内容");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "任务2的返回值";
        }, executor);

        CompletableFuture<String> future3 = future1.thenCombineAsync(future2, (result1, result2) -> {
            System.out.println("执行任务3的内容，需要等待任务1和任务2都执行完毕以后在执行");
            System.out.println("在任务3中获得的任务1和任务2的返回值是:" + result1 + ";" + result2);
            return "任务3的返回值";
        }, executor);
        System.out.println("最终任务3的返回结果是："+future3.get());

        CompletableFuture<Void> future4 = future1.thenAcceptBothAsync(future2, (result1, result2) -> {
            System.out.println("执行任务4的内容，需要等待任务1和任务2都执行完毕以后在执行");
            System.out.println("在任务4中获得的任务1和任务2的返回值是:" + result1 + ";" + result2);
        }, executor);

        CompletableFuture<Void> future5= future1.runAfterBothAsync(future2, () -> {
            System.out.println("执行任务5的内容，需要等待任务1和任务2都执行完毕以后在执行");
        }, executor);
    }


    private static void method3() throws InterruptedException, ExecutionException {
        CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        }, executor).thenRunAsync(() -> {
            System.out.println("执行任务2中的内容");
        }, executor);
        System.out.println(completableFuture.get()+"!!!");
    }


    private static void method7() throws InterruptedException, ExecutionException {
        CompletableFuture<Void> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        }, executor).thenAcceptAsync((result) -> {
            System.out.println("执行任务2中的内容，任务2中获得的结果是：" + result);
        },executor);
        System.out.println(completableFuture.get());
    }

    private static void method6() throws InterruptedException, ExecutionException {
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("执行任务1中的内容");
            return "任务1的返回值";
        }, executor).thenApplyAsync((result) -> {
            System.out.println("执行任务2中的内容，获得任务1的返回值是:" + result);
            return "任务2的返回值";
        }, executor);
        System.out.println("最终获得的返回值是:"+completableFuture.get());
    }

    private static void method5() throws InterruptedException, ExecutionException {
        //whenCompleteAsync 不需要返回值
        //handleAsync 需要返回值，即使后面exceptionally代码块，exceptionally代码块也不执行
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("任务1开始执行");
            int result = 5 / 0;
            return "任务1返回值";
        }, executor).handleAsync((result, exception) -> {
            System.out.println("任务2开始执行，任务2中接收的任务1的返回值是：" + result);
            return "任务2的返回值";
        }, executor);
        System.out.println(completableFuture.get());
    }

    private static void method2() throws InterruptedException, ExecutionException {
        //任务2要求再任务1执行完成以后执行，并且任务2中要使用任务1的返回值
        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + "线程开始执行");
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            int result=5/0;
            System.out.println(name + "线程执行完毕");
            return "线程1返回的结果";
        }, executor).whenCompleteAsync((result, exception) -> {
//            int temp=5/0;
            System.out.println("执行任务二的操作，在任务二中获得的任务1的返回值的是：" + result);
        }, executor).exceptionally((exception) -> {  //任务出现异常时执行，任务1出现异常，任务2会执行.只不过在任务2中获得任务1的结果为null
            System.out.println("任务1中的异常信息:" + exception.getMessage());
            return "异常处理后的返回值";
        });
        System.out.println(completableFuture.get());
    }

    private static void method1() throws InterruptedException, ExecutionException {
        //创建一个线程池   supplyAsync  有任务结果
        CompletableFuture<String> completableFuture =
                CompletableFuture.supplyAsync(() -> {
            System.out.println("执行的任务1");
            return "任务1执行的结果";
        }, executor);
        System.out.println(completableFuture.get());  //任务1执行的结果

        //runAsync 没有任务结果
        CompletableFuture<Void> completableFuture2 =
                CompletableFuture.runAsync(() -> {
            System.out.println("执行的任务2");
        }, executor);
        System.out.println(completableFuture2.get()); //null
    }
}
